//
//  Copyright 2012, Xamarin Inc.
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
using EmployeeDirectory.Core.Data;
using System.Text;

namespace EmployeeDirectory.Core.ViewModels;

public class PersonViewModel : ViewModelBase
{
	private IFavoritesRepository FavoritesRepository { get; set; }

	public PersonViewModel (Person person, IFavoritesRepository favoritesRepository)
	{
		if (person == null)
			throw new ArgumentNullException ("person");

		if (favoritesRepository == null)
			throw new ArgumentNullException ("favoritesRepository");

		Person = person;
		FavoritesRepository = favoritesRepository;

		PropertyGroups = new ObservableCollection<PropertyGroup> ();

		var general = new PropertyGroup ("General");
		general.Add ("Title", person.Title, PropertyType.Generic);
		general.Add ("Department", person.Department, PropertyType.Generic);
		general.Add ("Company", person.Company, PropertyType.Generic);
		general.Add ("Manager", person.Manager, PropertyType.Generic);
		general.Add ("Description", person.Description, PropertyType.Generic);

		if (general.Properties.Count > 0)
			PropertyGroups.Add (general);

		var phone = new PropertyGroup ("Phone");
		foreach (var p in person.TelephoneNumbers) {
			phone.Add ("Phone", p, PropertyType.Phone);
		}

		foreach (var p in person.HomeNumbers) {
			phone.Add ("Home", p, PropertyType.Phone);
		}

		foreach (var p in person.MobileNumbers) {
			phone.Add ("Mobile", p, PropertyType.Phone);
		}

		if (phone.Properties.Count > 0)
			PropertyGroups.Add (phone);

		var online = new PropertyGroup ("Online");
		online.Add ("Email", person.Email, PropertyType.Email);
		online.Add ("WebPage", CleanUrl (person.WebPage), PropertyType.Url);			
		online.Add ("Twitter", CleanTwitter (person.Twitter), PropertyType.Twitter);

		if (online.Properties.Count > 0)
			PropertyGroups.Add (online);

		var address = new PropertyGroup ("Address");
		address.Add ("Office", person.Office, PropertyType.Generic);
		address.Add ("Address", AddressString, PropertyType.Address);

		if (address.Properties.Count > 0)
			PropertyGroups.Add (address);
	}

	private static string CleanUrl (string url)
	{
		var trimmed = (url ?? "").Trim ();
		if (trimmed.Length == 0) return "";

		var upper = trimmed.ToUpperInvariant ();
		if (!upper.StartsWith ("HTTP")) {
			return "http://" + trimmed;
		} else {
			return trimmed;
		}
	}

	private static string CleanTwitter (string username)
	{
		var trimmed = (username ?? "").Trim ();
		if (trimmed.Length == 0) return "";

		if (!trimmed.StartsWith ("@")) {
			return "@" + trimmed;
		} else {
			return trimmed;
		}
	}

	#region View Data

	public Person Person { get; private set; }

	public ObservableCollection<PropertyGroup> PropertyGroups { get; private set; }

	public bool IsFavorite {
		get { return FavoritesRepository.IsFavorite (Person); }
	}
	public bool IsNotFavorite {
		get { return !FavoritesRepository.IsFavorite (Person); }
	}

	public string FavoriteStatusText {
		get { return IsFavorite ? "Added to favorites" : "Not in favorites"; }
	}

	string AddressString {
		get {
			var sb = new StringBuilder ();

			if (!string.IsNullOrWhiteSpace (Person.Street))
				sb.AppendLine (Person.Street.Trim ());

			if (!string.IsNullOrWhiteSpace (Person.POBox))
				sb.AppendLine (Person.POBox.Trim ());

			if (!string.IsNullOrWhiteSpace (Person.City))
				sb.AppendLine (Person.City.Trim ());

			if (!string.IsNullOrWhiteSpace (Person.State))
				sb.AppendLine (Person.State.Trim ());

			if (!string.IsNullOrWhiteSpace (Person.PostalCode))
				sb.AppendLine (Person.PostalCode.Trim ());

			if (!string.IsNullOrWhiteSpace (Person.Country))
				sb.AppendLine (Person.Country.Trim ());

			return sb.ToString ();
		}
	}

	public class PropertyGroup : IEnumerable<Property>
	{
		public string Title { get; private set; }
		public ObservableCollection<Property> Properties { get; private set; }

		public PropertyGroup (string title)
		{
			Title = title;
			Properties = new ObservableCollection<Property> ();
		}

		public void Add (string name, string value, PropertyType type)
		{
			if (!string.IsNullOrWhiteSpace (value))
				Properties.Add (new Property (name, value, type));
		}

		IEnumerator<Property> IEnumerable<Property>.GetEnumerator ()
		{
			return Properties.GetEnumerator ();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
		{
			return Properties.GetEnumerator ();
		}
	}

	public class Property
	{
		public string Name { get; private set; }
		public string Value { get; private set; }
		public PropertyType Type { get; private set; }

		public Property (string name, string value, PropertyType type)
		{
			Name = name;
			Value = value.Trim ();
			Type = type;
		}

		public override string ToString ()
		{
			return string.Format ("{0} = {1}", Name, Value);
		}
	}

	public enum PropertyType
	{
		Generic,
		Phone,
		Email,
		Url,
		Twitter,
		Address,
	}

	#endregion

	#region Commands

	public void ToggleFavorite ()
	{		
		if (FavoritesRepository.IsFavorite (Person)) {
			FavoritesRepository.Delete (Person);
		} else {
			FavoritesRepository.InsertOrUpdate (Person);
		}
		OnPropertyChanged ("IsFavorite");
		OnPropertyChanged ("FavoriteStatusText");
	}

	#endregion
}
